
package com.eworking.eim;

import java.util.List;
import java.util.Locale;

import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.filter.MessageTypeFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;

import com.eworking.eim.encrypt.EIMCryptoUtils;
import com.eworking.eim.encrypt.EIMEncryptProvider;
import com.eworking.eim.exception.EIMException;
import com.eworking.eim.message.EIMMessage;
import com.eworking.eim.message.EIMMessageManager;
import com.eworking.eim.notify.EIMNotifyManager;
import com.eworking.eim.receive.EIMAckMessageListener;
import com.eworking.eim.receive.EIMGroupMessageListener;
import com.eworking.eim.receive.EIMMessageListener;
import com.eworking.eim.receive.EIMRosterPresenceListener;
import com.eworking.eim.service.EIMChatService;
import com.eworking.eim.user.EIMAccountUtils;
import com.eworking.eim.user.EIMUserManager;
import com.eworking.eim.util.EIMLog;
import com.eworking.eim.xmpp.EIMConnectionListener;
import com.eworking.eim.xmpp.XMPPConnectionManager;

public class EIMChatManager {
    
    /** 日志输出标签 */
    private static final String _TAG = EIMChatManager.class.getSimpleName();
    
    private static EIMChatManager chatManager = null;
    
    private Context context = null;
    
    /** XMPP服务器连接管理 */
    private XMPPConnectionManager xmppConnectionManager = null;
    
    /** 是否已绑定服务，調用者退出時，自动退出服务 */
    private boolean isBind = false;
    
    public EIMChatService bindService = null;
    
    /** Android服务监听 */
    private BindServiceConnection serviceConnection = null;
    
    /** IM参数设置 */
    private EIMChatOptions chatOptions = null;
    
    /**  */
    private EIMEncryptProvider encryptProvider = null;
    
    /** 消息管理 */
    private EIMMessageManager messageManager = null;
    
    /** 消息通知管理 */
    private EIMNotifyManager notifyManager = null;
    
    private EIMChatManager() {
        this.chatOptions = new EIMChatOptions();
        this.serviceConnection = new BindServiceConnection();
        this.messageManager = EIMMessageManager.getInstance();
        // 聊天室设置
        this.chatOptions = new EIMChatOptions();
    }
    
    public static EIMChatManager getInstance() {
        if (chatManager == null) {
            chatManager = new EIMChatManager();
        }
        return chatManager;
    }
    
    /**
     * 初始化
     * 
     * @param context
     * @param xmppConnectionManager
     */
    public void init(Context context, XMPPConnectionManager xmppConnectionManager) {
        this.context = context;
        this.xmppConnectionManager = xmppConnectionManager;
        // 初始化
        this.messageManager.init(context, xmppConnectionManager, this.getChatOptions());
        // 消息通知
        this.notifyManager = EIMNotifyManager.getInstance(context);
        addPacketListeners();
    }
    
    /**
     * 添加所有消息接收监听器
     */
    private void addPacketListeners() {
        try {
            XMPPConnection connection = this.xmppConnectionManager.getConnection();
            // 添加消息的接受监听器[单聊]
            MessageTypeFilter messageTypeFilter = new MessageTypeFilter(Message.Type.chat);
            connection.addPacketListener(new EIMMessageListener(), messageTypeFilter);
            // 添加群组消息接收监听器[群聊]
            MessageTypeFilter groupMessageTypeFilter = new MessageTypeFilter(Message.Type.groupchat);
            connection.addPacketListener(new EIMGroupMessageListener(), groupMessageTypeFilter);
            // 添加回执消息接收监听器
            MessageTypeFilter ackMessageTypeFilter = new MessageTypeFilter(Message.Type.normal);
            connection.addPacketListener(new EIMAckMessageListener(), ackMessageTypeFilter);
            
            // 添加好友请求消息接收监听器
            PacketTypeFilter packetTypeFilter = new PacketTypeFilter(Presence.class) {
                
                public boolean accept(Packet paramPacket) {
                    if (!(paramPacket instanceof Presence)) {
                        return false;
                    }
                    Presence localPresence = (Presence) paramPacket;
                    return ((localPresence.getType().equals(Presence.Type.subscribed))
                        || (localPresence.getType().equals(Presence.Type.subscribe))
                        || (localPresence.getType().equals(Presence.Type.unsubscribed)) || (localPresence.getType()
                        .equals(Presence.Type.unsubscribe)));
                }
            };
            connection.addPacketListener(new EIMRosterPresenceListener(), packetTypeFilter);
        } catch (Exception e) {
            EIMLog.e(_TAG, "与XMPP服务器连接断开：" + e.getMessage());
        }
    }
    
    /**
     * 用户登陆
     * 
     * @param account 用户账号
     * @param password 用户密码
     * @param callBack
     */
    public void login(String account, String password, EIMCallBack callBack) {
        try {
            // 用户登陆
            EIMSessionManager.getInstance(context).login(account, password, callBack);
            // 绑定服务
            bindService();
        } catch (Exception e) {
            EIMLog.e(_TAG, "登陆XMPP服务失败：" + e.getMessage());
            callBack.onError(EIMCallBack.ERROR_EXCEPTION, "登陆XMPP服务失败");
        }
    }
    
    /**
     * 退出登陆
     */
    public void logout() {
        try {
            EIMSessionManager.getInstance(context).logout();
            this.messageManager.clear();
            EIMManager.getInstance().isAppInited = false;
            // 解除绑定
            this.unbindService();
        } catch (Exception e) {
            EIMLog.e(_TAG, "退出XMPP服务失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存消息信息
     * 
     * @param message 消息实体
     */
    public void saveMessage(EIMMessage message) {
        this.messageManager.saveMessage(message);
    }
    
    /**
     * 获取消息信息
     * 
     * @param msgId 消息ID
     * @return
     */
    public EIMMessage getMessage(String msgId) {
        return this.messageManager.getMessage(msgId);
    }
    
    /**
     * 发送消息
     * 
     * @param message 消息实体
     */
    public void sendMessage(EIMMessage message) {
        this.sendMessage(message, null);
    }
    
    /**
     * 发送消息
     * 
     * @param message 消息实体
     * @param callBack
     */
    public void sendMessage(EIMMessage message, EIMCallBack callBack) {
        this.messageManager.sendMessage(message, callBack);
    }
    
    /**
     * 发送群组消息
     * 
     * @param message 消息实体
     * @param callBack
     */
    public void sendGroupMessage(EIMMessage message, EIMCallBack callBack) {
        this.messageManager.sendGroupMessage(message, callBack);
    }
    
    /**
     * 确认消息已读，发送已读回执
     */
    public void ackMessageRead(String account, String msgId) {
        this.messageManager.ackMessageRead(account, msgId);
    }
    
    /**
     * 删除会话及消息
     * 
     * @param conversKey 参与者ID或群组ID
     */
    public void deleteConversation(String conversKey) {
        this.messageManager.deleteConversation(conversKey);
    }
    
    /**
     * 清空当前参与者或群组的会话消息记录
     * 
     * @param conversKey 参与者ID或群组ID
     */
    public void clearConversation(String conversKey) {
        this.messageManager.clearConversation(conversKey);
    }
    
    /**
     * 获取所有未读取的消息数量
     * 
     * @return
     */
    public int getUnreadMsgsCount() {
        return this.messageManager.getUnreadMsgsCount();
    }
    
    /**
     * 添加XMPP连接监听
     * 
     * @param connectionListener
     */
    public void addConnectionListener(final EIMConnectionListener connectionListener) {
        this.messageManager.addConnectionListener(connectionListener);
    }
    
    /**
     * 删除XMPP连接监听
     * 
     * @param connectionListener
     */
    public void removeConnectionListener(EIMConnectionListener connectionListener) {
        this.messageManager.removeConnectionListener(connectionListener);
    }
    
    /**
     * 绑定服务
     */
    private void bindService() {
        if (this.isBind) {
            return;
        }
        EIMLog.d(_TAG, "绑定服务，調用者退出時，自动退出服务");
        Intent intent = new Intent(this.context, EIMChatService.class);
        // 绑定服务
        this.context.bindService(intent, this.serviceConnection, Context.BIND_AUTO_CREATE);
        this.isBind = true;
    }
    
    /**
     * 解除绑定
     */
    public void unbindService() {
        if (this.isBind) {
            EIMLog.d(_TAG, "解除服务绑定：BindService");
            this.context.unbindService(this.serviceConnection);
            this.isBind = false;
        }
    }
    
    /**
     * 获取所有好友的昵称
     * 
     * @return
     */
    public List<String> getRosterNickNames() {
        return EIMUserManager.getInstance().getRosterNickNames();
    }
    
    /**
     * 接受加为好友
     * 
     * @param account JID
     * @param isAccept 是否接受
     */
    public void acceptInvitation(String account) {
        EIMUserManager.getInstance().acceptInvitation(EIMAccountUtils.getJIDFromAccount(account), true);
    }
    
    /**
     * 拒绝加为好友
     * 
     * @param account 用户账号
     */
    public void refuseInvitation(String account) {
        EIMUserManager.getInstance().refuseInvitation(account);
    }
    
    /**
     * 处理离线好友申请
     */
    public void processOfflinePresences() {
        EIMUserManager.getInstance().processOfflinePresences();
    }
    
    /**
     * 发送回执广播消息
     * 
     * @param account 用户账号
     * @param msgId 消息ID
     */
    public void notifiyAckMessage(String account, String msgId) {
        this.notifyManager.notifyAckMessage(account, msgId);
    }
    
    /**
     * 消息通知
     * 
     * @param message
     */
    public void notifyMessage(EIMMessage message) {
        this.notifyManager.notifyMessage(message);
    }
    
    /**
     * 窗口恢复
     */
    public void activityResumed() {
        if (this.notifyManager != null) {
            this.notifyManager.resetNotificationCount();
            this.notifyManager.cancelNotificaton();
        }
    }
    
    /**
     * Android绑定服务监听器
     * 
     * @author yangsong
     * @since 1.0
     * @version 2014年7月16日
     */
    private class BindServiceConnection implements ServiceConnection {
        
        public void onServiceConnected(ComponentName componentname, IBinder ibinder) {
            bindService = ((EIMChatService.EIMBinder) ibinder).getService();
            EIMLog.d(_TAG, "连接服务：BindService");
        }
        
        public void onServiceDisconnected(ComponentName name) {
            bindService = null;
            EIMLog.d("chat", "断开服务：BindService");
        }
    }
    
    public EIMChatOptions getChatOptions() {
        return this.chatOptions;
    }
    
    public void setEncryptProvider(EIMEncryptProvider encryptProvider) {
        this.encryptProvider = encryptProvider;
    }
    
    public EIMEncryptProvider getEncryptProvider() {
        if (this.encryptProvider == null) {
            this.encryptProvider = new EIMEncryptProvider() {
                
                public byte[] encrypt(byte abyte0[], String paramString) {
                    try {
                        return EIMCryptoUtils.getInstance().encrypt(abyte0);
                    } catch (Exception localException) {
                        return abyte0;
                    }
                }
                
                public byte[] decrypt(byte abyte0[], String paramString) {
                    try {
                        return EIMCryptoUtils.getInstance().decrypt(abyte0);
                    } catch (Exception localException) {
                        return abyte0;
                    }
                }
            };
        }
        return this.encryptProvider;
    }
    
    /**
     * 创建账号
     * 
     * @param account
     * @param password
     * @throws EIMException
     */
    public void createAccountOnServer(String account, String password) throws EIMException {
        String strLowerAccount = account.toLowerCase(Locale.UK);
        if (!(strLowerAccount.equals(account))) {
            throw new EIMException("User name does not support the capital letters");
        }
        if (!(account.startsWith(EIMConfig.getInstance().getEntCode()))) {
            account = EIMConfig.getInstance().getEntCode() + "_" + account;
        }
        EIMSessionManager.getInstance(this.context).createAccountXMPP(account, password);
    }
    
    /**
     * 修改密码
     * 
     * @param paramString
     */
    public void changePasswordOnServer(String password) {
        EIMSessionManager.getInstance(this.context).changePasswordXMPP(password);
    }
    
    /**
     * 当前用户账号
     * 
     * @return
     */
    public String getCurrentAccount() {
        return EIMSessionManager.getInstance(context).getCurrentUser().getAccount();
    }
    
    public void setChatOptions(EIMChatOptions chatOptions) {
        this.chatOptions = chatOptions;
    }
}
